<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
       /*  1.闭包函数：
            用一个函数包裹其他函数即构建成闭包结构
            借助于函数本身局部作用域特性，通过返回函数，可以扩展函数的取值范围
            可以防止全局变量被污染 */

        var num="全局变量num";
        function f1(){
            var num=100;//局部变量
            return function(){
                console.log(num);
                num++;
            };

        }
        var res=f1();
        res();
        res();
        res();

        console.log("==========");
        // IIFE:(Imdiately Invoked Function Expression ) 立即执行的函数表达式,实际上就是闭包函数自执行方案
        var num2="全局变量num2";
        var f2=(function(){
            var num2=0;
            return function(){
                console.log(num2);
                num2++;
            }
        })();
        console.log(f2);

        //很多情况下，可能不会让自执行函数接受返回值，一般使用全局window进行承载共享，此时会将window作为实参进行传递
        (function(w){
            var num=888;
            w.f3=function(){
                console.log(num);
                num++;
            };
        })(window);
        f3();
        f3();

        // ES6中语法中使用let和const具有块级作用域
        {
            let num3=999;

            //虽然函数定义在代码块中，但是因为该函数是ES5中普通定义函数的方式，没有块级作用域概念
            //所以实际上该函数仍然是定义在全局环境中(window)
            function f4(){
                console.log(num3);
                num3++;
            }
        }
        // console.log(num3);//let声明的变量具有块级作用域
        f4();
        f4();

       /*  IIFE和块作用域
            IIFE : (Imdiately Invoked Function Expression ) 立即执行的函数表达式

            ES5 语法中没有块作用域，因此在实际项目开发中，为方式全局变量因变量提升被污染会采用IIFE模式；

            ES6 语法中let 被构建了块作用域，因此可以使用块定义方式替代IIFE模式 */

    </script>
</head>
<body>
    
</body>
</html>